/**
 * @class cfw-core
 * @author DuskyHuang 圣子
 * @description 客户端框架门面，向使用者提供接口导出
*/

import { Notifier } from "./notifier";
import { notifier, bridge, controllers, mediators, proxies } from "./boot";
import Controller from "./mvc/Controller";
import Mediator from "./mvc/Mediator";
import Proxy from "./mvc/Proxy";
import TimerSystem from "./ecs/TimerSystem";
import AudioManager from "../managers/audio-manager";
import ResManager from "../managers/res-manager";
import UIManager from "../managers/ui-manager";
import NetManager from "../managers/net-manager";
import SceneManager from "../managers/scene-manager";
import Root from "../managers/root";
import { IsOnLoadCalled } from "../utils";
import { director } from "cc";

export default class core {

    /** ———————————————————— 管理器/系统 ———————————————————— **/

    /** 时间管理器 */ public static readonly timer: TimerSystem = TimerSystem.instance;

    /** 资源管理器 */ public static readonly res: ResManager = ResManager.instance;

    /** UI管理器 */ public static readonly ui: UIManager = UIManager.instance;

    /** 场景管理器 */ public static readonly scene: SceneManager = SceneManager.instance;

    /** 音频管理器 */ public static get audio(): AudioManager { return AudioManager.instance; }

    /** 网络管理器 */  public static get net(): NetManager { return NetManager.instance; }

    /** ———————————————————— 事件/通知 ———————————————————— **/

    /** 通知发送器 */ public static readonly notifier: Notifier = notifier;

    /** 通知桥接器 */ public static readonly bridge: Notifier = bridge;

    public static get root(): Root {
        if (IsOnLoadCalled(Root.instance)) return Root.instance;
        return director.getScene().getComponentInChildren(Root);
    }

    /**
     * 注册通知
     * @param type 通知名
     * @param handler 回调函数
     * @param observer 回调上下文
     * @param priority 回调优先级，越大越先调用，默认=0
     * @return 是否成功注册
    */
    public static on(type: string | number, handler: Handler, observer?: any, priority: number = 0): bool.res {
        return this.notifier.attach(type, handler, observer, false, priority);
    }

    /**
     * 单次注册通知
     * @param type 通知名
     * @param handler 回调函数
     * @param observer 回调上下文
     * @param priority 回调优先级，越大越先调用，默认=0
     * @return 是否成功注册
    */
    public static once(type: string | number, handler: Handler, observer?: any, priority: number = 0): bool.res {
        return this.notifier.attach(type, handler, observer, true, priority);
    }

    /**
     * 注销通知
     * @param type 通知名
     * @param handler 回调函数
     * @param observer 回调上下文
     * @return 移除条数（命中条数）
     * @explain 当指定回调上下文时，只有与该上下文相同的一条通知监听会被移除，否则全部移除
    */
    public static off(type: string | number, handler: Handler, observer?: any): num.int {
        return this.notifier.detach(type, handler, observer);
    }

    /**
     * 发送通知
     * @param type 通知类型
     * @params args 参数罗列
     * @return 移除条数（命中条数）
     */
    public static notify(type: string | number, ...args: any[]): num.int {
        return this.notifier.dispatch(type, ...args);
    }

    /**
     * 移除某上下文相关的所有监听通知
     * @param observer 回调上下文
     * @return 移除条数（命中条数）
     */
    public static unload(observer: any): num.int {
        return this.notifier.unload(observer);
    }

    /**
     * 清空某类通知
     * @param type 需要移除的通知类型
     * @return 是否有通知被移除
     */
    public static clear(type: string | number): bool.exist {
        return this.notifier.clear(type);
    }

    /** ———————————————————— 核心成员 ———————————————————— **/

    /** 数据代理成员 */ public static readonly proxies = proxies;

    /** 中介者成员 */ public static readonly mediators = mediators;

    /** 控制器成员 */ public static readonly controllers = controllers;

    /** 
     * 获取指定类型数据代理实例
     * @param Controller 数据代理的类型
     * @return 数据代理实例
     */
    public static getProxy<P extends Proxy>(Proxy: Class<P>): P | null {
        for (let p of this.proxies) { if (p instanceof Proxy) return p; }
        return null;
    }

    /** 
     * 获取所有指定类型数据代理实例
     * @param Controller 数据代理的类型
     * @return 所有数据代理实例
     */
    public static getProxies<P extends Proxy>(Proxy: Class<P>): P[] {
        return this.proxies.filter(p => p instanceof Proxy) as P[];
    }

    /** 
     * 获取指定类型中介实例
     * @param Controller 中介者的类型
     * @return 中介者实例
     */
    public static getMediator<M extends Mediator>(Mediator: Class<M>): M | null {
        for (let m of this.mediators) { if (m instanceof Mediator) return m; }
        return null;
    }

    /** 
     * 获取所有指定类型中介者实例
     * @param Controller 中介者的类型
     * @return 所有中介者实例
     */
    public static getMediators<M extends Mediator>(Mediator: Class<M>): M[] {
        return this.mediators.filter(m => m instanceof Mediator) as M[];
    }

    /** 
     * 获取指定类型控制器实例
     * @param Controller 控制器的类型
     * @return 控制器实例
     */
    public static getController<C extends Controller>(Controller: Class<C>): C | null {
        for (let c of this.controllers) { if (c instanceof Controller) return c; }
        return null;
    }

    /** 
     * 获取所有指定类型控制器实例
     * @param Controller 控制器的类型
     * @return 所有控制器实例
     */
    public static getControllers<C extends Controller>(Controller: Class<C>): C[] {
        return this.controllers.filter(c => c instanceof Controller) as C[];
    }
}